package cn.nexttec.noteplayer.ui.widget

import android.app.Activity
import android.app.Application
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.os.Message
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextWatcher
import android.view.Gravity
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.widget.EditText
import android.widget.GridLayout
import android.widget.PopupWindow
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.recyclerview.widget.LinearLayoutManager
import cn.nexttec.noteplayer.R
import cn.nexttec.noteplayer.common.formatPosition
import cn.nexttec.noteplayer.common.formatSpeed
import cn.nexttec.noteplayer.databinding.DialogAddFavrioteBinding
import cn.nexttec.noteplayer.databinding.DialogAddImageBinding
import cn.nexttec.noteplayer.databinding.DialogAlertBinding
import cn.nexttec.noteplayer.databinding.DialogCameraPermissionRequestBinding
import cn.nexttec.noteplayer.databinding.DialogCropVideoBinding
import cn.nexttec.noteplayer.databinding.DialogPermissionRequestBinding
import cn.nexttec.noteplayer.databinding.DialogPlaylistBinding
import cn.nexttec.noteplayer.databinding.DialogScreenShotAlertBinding
import cn.nexttec.noteplayer.databinding.DialogSetPasswordBinding
import cn.nexttec.noteplayer.databinding.DialogSettingPasswordBinding
import cn.nexttec.noteplayer.databinding.DialogTrackSelectorBinding
import cn.nexttec.noteplayer.databinding.LayoutColorGridBinding
import cn.nexttec.noteplayer.databinding.LayoutMenuBinding
import cn.nexttec.noteplayer.databinding.PopupPlaybackSpeedBinding
import cn.nexttec.noteplayer.models.TrackSelectionOption
import cn.nexttec.noteplayer.models.VideoFileInfo
import cn.nexttec.noteplayer.ui.adapters.PlaylistVideoAdapter
import cn.nexttec.noteplayer.ui.adapters.TrackAdapter
import com.bumptech.glide.Glide
import kotlinx.coroutines.*
import java.io.File
import java.lang.ref.WeakReference

object PopupDialog : Application.ActivityLifecycleCallbacks {
    private var currentActivityRef: WeakReference<Activity>? = null
    private val currentActivity: Activity? get() = currentActivityRef?.get()

    private var popupWindow: PopupWindow? = null
    private val popupWindows: LinkedHashMap<String, PopupWindow> = linkedMapOf()

    private var autoDismissJob: Job? = null

    var onDismiss: (() -> Unit)? = null
    var onShow:(()->Unit)? = null

    fun init(application: Application) {
        application.registerActivityLifecycleCallbacks(this)
    }

    enum class Position { TOP, BOTTOM, CENTER }

    fun isShowing(tag: String): Boolean {
        return popupWindows.containsKey(tag)
    }

    private fun showAsDropDown(
        contentView: View,
        tag: String = "PopupWindows",
        anchor: View,
        xOffset: Int = 0,
        yOffset: Int = 0,
        canOutsideTouchable: Boolean = true,
        dismissPreviousDialog: Boolean = true,
        onDismiss: (() -> Unit)? = null
    ) {
        if (dismissPreviousDialog) {
            popupWindows[tag]?.dismiss()
            popupWindows.remove(tag)
        }

        popupWindow = PopupWindow(
            contentView,
            ViewGroup.LayoutParams.WRAP_CONTENT,  // 使用内容自身宽度
            ViewGroup.LayoutParams.WRAP_CONTENT,
            true
        ).apply {
            isOutsideTouchable = canOutsideTouchable
            isFocusable = !canOutsideTouchable
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        }
        popupWindow?.setOnDismissListener {
//            popupWindows.remove(tag)
            onDismiss?.invoke()
        }

        popupWindows[tag] = popupWindow!!
        popupWindow!!.showAsDropDown(anchor, xOffset, yOffset)
    }


    fun showFileMenu(anchorView: View, onClick: (String) -> Unit) {
        val tag = "menu"
        val binding = LayoutMenuBinding.inflate(LayoutInflater.from(currentActivity!!))
        binding.btnScan.setOnClickListener {
            onClick("scan")
            dismiss(tag)
        }
        binding.btnPrivate.setOnClickListener {
            onClick("private")
            dismiss(tag)
        }

        binding.btnSort.setOnClickListener {
            onClick("sort")
            dismiss(tag)
        }

        showAsDropDown(binding.root, tag, anchorView, xOffset = -50, yOffset = 50)
    }



    private fun show(
        contentView: View,
        tag: String = "PopupWindows",
        position: Position = Position.BOTTOM,
        canOutsideTouchable: Boolean = true,
        dismissPreviousDialog: Boolean = true,
        isHeghtMatchParent: Boolean = true,
        isWidthMatchParent: Boolean = true,
        dismiss: (() -> Unit)? = null
    ) {
        if (dismissPreviousDialog) {
            popupWindows[tag]?.dismiss()
            popupWindows.remove(tag)
        }

        popupWindow = PopupWindow(
            contentView,
            if (isWidthMatchParent) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT,
            if (isHeghtMatchParent) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT,
            true
        ).apply {
            isOutsideTouchable = canOutsideTouchable
            isFocusable = !canOutsideTouchable
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            contentView.fitsSystemWindows = false
        }
        onShow?.invoke()
        popupWindow?.setOnDismissListener {
            onDismiss?.invoke()
            dismiss?.invoke()
        }
        popupWindows[tag] = popupWindow!!
        val activity = currentActivity ?: return
        val rootView = activity.window?.decorView ?: contentView
        when (position) {
            Position.TOP -> {
                popupWindow?.showAtLocation(rootView, Gravity.TOP, 0, 0)
                slideIn(contentView, fromTop = true)
            }

            Position.BOTTOM -> {
                popupWindow?.showAtLocation(rootView, Gravity.BOTTOM, 0, 0)
                slideIn(contentView, fromTop = false)
            }

            Position.CENTER -> {
                popupWindow?.showAtLocation(rootView, Gravity.CENTER, 0, 0)
                fadeIn(contentView)
            }
        }
    }

    private fun slideIn(view: View, fromTop: Boolean) {
        view.translationY = if (fromTop) -view.height.toFloat() else view.height.toFloat()
        view.alpha = 0f
        view.animate()
            .translationY(0f)
            .alpha(1f)
            .setDuration(300)
            .setInterpolator(DecelerateInterpolator())
            .start()
    }

    private fun fadeIn(view: View) {
        view.alpha = 0f
        view.animate()
            .alpha(1f)
            .setDuration(300)
            .start()
    }

    fun dismiss(tag: String? = null) {
        autoDismissJob?.cancel()
        autoDismissJob = null

        if (tag != null) {
            popupWindows[tag]?.dismiss()
            popupWindows.remove(tag)
        } else {
            val lastEntry = popupWindows.entries.lastOrNull()
            lastEntry?.let {
                it.value.dismiss()
                popupWindows.remove(it.key)
            }
        }
    }

    fun dismissAll() {
        autoDismissJob?.cancel()
        autoDismissJob = null

        popupWindows.values.forEach { it.dismiss() }
        popupWindows.clear()
    }

    override fun onActivityCreated(p0: Activity, p1: Bundle?) = Unit
    override fun onActivityStarted(p0: Activity) = Unit
    override fun onActivityResumed(p0: Activity) {
        currentActivityRef = WeakReference(p0)
    }

    override fun onActivityPaused(p0: Activity) = Unit
    override fun onActivityStopped(p0: Activity) = Unit
    override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) = Unit
    override fun onActivityDestroyed(p0: Activity) {
        if (p0 == currentActivityRef?.get()) {
            currentActivityRef?.clear()
        }
        popupWindows.entries.removeIf { (_, popup) ->
            popup.contentView.context == p0
        }
    }

    fun showSpeedDialog(currentSpeed: Float, anchor: View, onSpeedChange: (Float) -> Unit) {
        val binding = PopupPlaybackSpeedBinding.inflate(LayoutInflater.from(currentActivity))
        val speeds = listOf(0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2f)
        var index = speeds.indexOf(currentSpeed)
        var newSpeed = currentSpeed

        fun resetAutoDismiss() {
            autoDismissJob?.cancel()
            autoDismissJob = CoroutineScope(Dispatchers.Main).launch {
                delay(2000)
                dismiss("speed")
            }
        }

        val updateUI = {
            binding.tvSpeed.text = formatSpeed(newSpeed)
            onSpeedChange(newSpeed)

            binding.btnAdd.setImageResource(
                if (index == speeds.lastIndex) R.drawable.baseline_arrow_right_24_gray else R.drawable.baseline_arrow_right_24
            )
            binding.btnMinus.setImageResource(
                if (index == 0) R.drawable.baseline_arrow_left_24_gray else R.drawable.baseline_arrow_left_24
            )

            resetAutoDismiss()
        }

        binding.btnAdd.setOnClickListener {
            if (index < speeds.lastIndex) {
                index++
                newSpeed = speeds[index]
                updateUI()
            }
        }

        binding.btnMinus.setOnClickListener {
            if (index > 0) {
                index--
                newSpeed = speeds[index]
                updateUI()
            }
        }

        // 初始化显示当前速度
        binding.tvSpeed.text = formatSpeed(currentSpeed)
        updateUI()

        showAsDropDown(binding.root, "speed", anchor)
    }

    fun showStoragePermissionRequestDialog(onConfirm: () -> Unit, onReject: () -> Unit) {
        val binding = DialogPermissionRequestBinding.inflate(LayoutInflater.from(currentActivity))
        binding.btnCancel.setOnClickListener {
            onReject()
            dismiss()
        }
        binding.btnConfirm.setOnClickListener {
            onConfirm()
            dismiss()
        }

        show(binding.root, "Permission", Position.CENTER, false, false)
    }

    fun showCameraPermissionRequestDialog(onConfirm: () -> Unit, onReject: () -> Unit) {
        val binding =
            DialogCameraPermissionRequestBinding.inflate(LayoutInflater.from(currentActivity))
        binding.btnCancel.setOnClickListener {
            onReject()
            dismiss()
        }
        binding.btnConfirm.setOnClickListener {
            onConfirm()
            dismiss()
        }

        show(binding.root, "Permission", Position.CENTER, false, false)
    }

    fun showPasswordInput(onConfirm: (String) -> Unit) {
        var password: String = ""
        val binding = DialogSetPasswordBinding.inflate(LayoutInflater.from(currentActivity!!))
        val inputs = listOf(binding.etPass1, binding.etPass2, binding.etPass3, binding.etPass4)

        PasswordInputHelper.attachInputs(inputs) { text ->
            password = text

        }

        binding.btnConfirm.setOnClickListener {
            if (password.length == 4) {
                onConfirm(password)
                dismiss("Password")
            }
        }

        binding.btnCancel.setOnClickListener {
            dismiss("Password")
        }

        show(
            binding.root,
            tag = "Password",
            position = Position.CENTER,
            canOutsideTouchable = false,
            dismissPreviousDialog = true
        )
    }


    fun showPlaylist(
        current: VideoFileInfo,
        list: List<VideoFileInfo>,
        onPlay: (VideoFileInfo) -> Unit,
        dismiss: () -> Unit
    ) {
        val binding = DialogPlaylistBinding.inflate(LayoutInflater.from(currentActivity))
        val adapter = PlaylistVideoAdapter {
            onPlay(it)
        }
        binding.rvPlaylist.adapter = adapter
        adapter.setPlayList(current, list)
        binding.rvPlaylist.layoutManager = LinearLayoutManager(currentActivity!!)

        show(
            binding.root,
            tag = "playlist",
            position = Position.CENTER,
            canOutsideTouchable = true,
            dismissPreviousDialog = true,
            isHeghtMatchParent = false,
            isWidthMatchParent = false,
            dismiss = dismiss
        )

    }


    fun showPrivatePasswordSettingDialog(onConfirm: (String) -> Unit, onCancel: () -> Unit) {
        val binding = DialogSettingPasswordBinding.inflate(LayoutInflater.from(currentActivity!!))

        // 所有密码输入框
        val pwdFields = listOf(
            binding.etPwd1, binding.etPwd2, binding.etPwd3, binding.etPwd4
        )
        val confirmFields = listOf(
            binding.etConfirm1, binding.etConfirm2, binding.etConfirm3, binding.etConfirm4
        )

        // 设置所有 EditText 只允许输入一位数字、自动跳转、退格自动回退
        fun setupFields(fields: List<EditText>) {
            for (i in fields.indices) {
                val current = fields[i]
                current.filters = arrayOf(InputFilter.LengthFilter(1))
                current.inputType = InputType.TYPE_CLASS_NUMBER
                current.setTextColor(Color.BLACK)
                current.gravity = Gravity.CENTER

                current.addTextChangedListener(object : TextWatcher {
                    override fun afterTextChanged(s: Editable?) {
                        if (!s.isNullOrEmpty()) {
                            if (i < fields.size - 1) fields[i + 1].requestFocus()
                        }
                    }

                    override fun beforeTextChanged(
                        s: CharSequence?,
                        start: Int,
                        count: Int,
                        after: Int
                    ) {
                    }

                    override fun onTextChanged(
                        s: CharSequence?,
                        start: Int,
                        before: Int,
                        count: Int
                    ) {
                    }
                })

                current.setOnKeyListener { v, keyCode, event ->
                    if (event.action == KeyEvent.ACTION_DOWN &&
                        keyCode == KeyEvent.KEYCODE_DEL &&
                        current.text.isEmpty() &&
                        i > 0
                    ) {
                        fields[i - 1].apply {
                            setText("")
                            requestFocus()
                        }
                        true
                    } else {
                        false
                    }
                }
            }
        }

        setupFields(pwdFields)
        setupFields(confirmFields)

        // 确认按钮逻辑
        binding.btnConfirm.setOnClickListener {
            val pwd = pwdFields.joinToString("") { it.text.toString() }
            val confirm = confirmFields.joinToString("") { it.text.toString() }

            if (pwd.length != 4 || confirm.length != 4) {
                Toast.makeText(currentActivity, "请输入完整的 4 位密码", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            if (pwd != confirm) {
                Toast.makeText(currentActivity, "两次输入的密码不一致", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            dismiss("PasswordSetting")
            onConfirm(pwd)  // ← 把密码传出去
        }

        // 取消按钮逻辑
        binding.btnCancel.setOnClickListener {
            dismiss("PasswordSetting")
            onCancel()
        }

        show(
            binding.root,
            "PasswordSetting",
            Position.CENTER
        )
    }

    fun showSoundTrackSelectDialog(
        tracks: List<TrackSelectionOption>,
        selected: Int = 0,
        onSelected: (TrackSelectionOption, Int) -> Unit
    ) {
        val binding = DialogTrackSelectorBinding.inflate(LayoutInflater.from(currentActivity!!))
        val adapter = TrackAdapter(tracks, selected) { track, index ->
            onSelected(track, index)
            dismiss("sound_track")
        }
        binding.rvList.adapter = adapter
        binding.rvList.layoutManager = LinearLayoutManager(currentActivity!!)
        show(binding.root, "sound_track", Position.CENTER, true, true, false, false)
    }

    fun showVideoCropDialog(
        videoFileInfo: VideoFileInfo,
        startPos: Long,
        endPos: Long,
        onCrop: (String) -> Unit,
        onCancel: () -> Unit
    ) {
        val binding = DialogCropVideoBinding.inflate(LayoutInflater.from(currentActivity!!))
        var name = "${startPos.formatPosition()}-${endPos.formatPosition()}"
        binding.etName.setText(name)
        binding.btnConfirm.setOnClickListener {
            name = binding.etName.text.toString()
            if (name.isEmpty()) {
                Toast.makeText(currentActivity!!, "剪辑名称不能为空", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            onCrop(name)
            dismiss("video_crop")
        }
        binding.btnClose.setOnClickListener {
            dismiss("video_crop")
        }
        show(binding.root, "video_crop", Position.CENTER, false, false, false, false)
    }

    fun showAlertDialog(
        message: String,
        onConfirm: () -> Unit,
        onCancel: ((String) -> Unit)? = null
    ) {
        val tag = "alert"
        val binding = DialogAlertBinding.inflate(LayoutInflater.from(currentActivity))
        binding.tvMessage.text = message
        binding.btnConfirm.setOnClickListener {
            onConfirm()
            dismiss(tag)
        }
        binding.btnClose.setOnClickListener {
            dismiss(tag)
        }
        show(binding.root, tag, Position.CENTER, false, true, false, false)
    }

    fun showColorPicker(onColorSelected: (Int) -> Unit) {
        val binding = LayoutColorGridBinding.inflate(LayoutInflater.from(currentActivity!!))
        // 9种颜色
        val colors = listOf(
            Color.BLACK,
            Color.RED,
            Color.GREEN,
            Color.BLUE,
            Color.YELLOW,
            Color.MAGENTA,
            Color.rgb(255, 165, 0), // 橙色
            Color.DKGRAY,
            Color.WHITE
        )

        val sizeDp = 30 // 30dp 更小更紧凑
        val density = currentActivity!!.resources.displayMetrics.density
        val sizePx = (sizeDp * density).toInt()
        val marginPx = (8 * density).toInt() // 8dp 间距

        colors.forEach { color ->

            val colorView = View(currentActivity!!).apply {
                layoutParams = GridLayout.LayoutParams().apply {
                    width = sizePx
                    height = sizePx
                    setMargins(marginPx, marginPx, marginPx, marginPx)
                }
                background = GradientDrawable().apply {
                    shape = GradientDrawable.OVAL
                    setColor(color)
                    setStroke(2, Color.BLACK)
                }
                setOnClickListener {
                    onColorSelected(color)
                    dismiss("color_picker")
                }
            }
            binding.gridColors.addView(colorView)
        }

        binding.btnCancel.setOnClickListener {
            dismiss("color_picker")
        }

        show(
            binding.root, "color_picker", Position.CENTER, false,
            dismissPreviousDialog = true,
            isHeghtMatchParent = false,
            isWidthMatchParent = false
        )
    }

    fun showScreenShotAlert(
        videoFileInfo: VideoFileInfo,
        tempImagePath: String,
        onEdit: (String) -> Unit,
        onConfirm: (String) -> Unit,
        onCancel: ((String) -> Unit)? = null
    ) {
        val tag = "ScreenShot"
        val binding = DialogScreenShotAlertBinding.inflate(LayoutInflater.from(currentActivity!!))
        Glide.with(currentActivity!!.baseContext).load(File(tempImagePath))
            .into(binding.ivScreenshot)
        binding.btnClose.setOnClickListener {
            onCancel?.invoke(tempImagePath)
            dismiss(tag)
        }
        binding.btnEdit.setOnClickListener {
            onEdit(tempImagePath)
            dismiss(tag)
        }
        binding.btnSave.setOnClickListener {
            onConfirm(tempImagePath)
            dismiss(tag)
        }
        show(
            binding.root, tag, Position.CENTER, false, dismissPreviousDialog = true,
            isHeghtMatchParent = false,
            isWidthMatchParent = false
        )
    }

    fun showDialogImageAdd(
        videoFileInfo: VideoFileInfo,
        imagePath: String,
        position: Long,
        onConfirm: (String) -> Unit,
        onCancel: () -> Unit
    ) {
        val tag = "add_image"
        val binding = DialogAddImageBinding.inflate(LayoutInflater.from(currentActivity))
        binding.btnClose.setOnClickListener {
            dismiss(tag)
        }
        val defaultName = position.formatPosition()
        binding.etName.setText(defaultName)
        binding.btnSave.setOnClickListener {
            var name = binding.etName.text.toString()
            if (name.isBlank()) {
                name = defaultName
            }
            onConfirm(name)
            dismiss(tag)
        }
        Glide.with(currentActivity!!.baseContext).load(File(imagePath))
            .into(binding.ivScreenshot)
        show(
            binding.root, tag, Position.CENTER, false, dismissPreviousDialog = true,
            isHeghtMatchParent = false,
            isWidthMatchParent = false
        )
    }


    fun addFavorite(imagePath: String, currentPosition: Long, onSave:(String, Long)->Unit, onCancel: () -> Unit) {
        val tag = "favorite"
        val binding = DialogAddFavrioteBinding.inflate(LayoutInflater.from(currentActivity!!))
        binding.btnClose.setOnClickListener {
            onCancel()
            dismiss(tag)
        }
        var name = currentPosition.formatPosition()
        binding.etName.setText(name)
        binding.btnSave.setOnClickListener {
            name = binding.etName.text.toString()
            if (name.isBlank()){
                name = currentPosition.formatPosition()
            }
            onSave(name, currentPosition)
            dismiss(tag)
        }

        Glide.with(currentActivity!!.baseContext).load(File(imagePath))
            .into(binding.ivScreenshot)
        show(
            binding.root, tag, Position.CENTER, false, dismissPreviousDialog = true,
            isHeghtMatchParent = false,
            isWidthMatchParent = false
        )
    }
}
